package com.vitalgateway.service;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import com.dtflys.forest.Forest;
import com.dtflys.forest.http.ForestRequest;
import com.vitalgateway.component.annotations.Log;
import com.vitalgateway.component.interceptor.CommonForestInterceptor;
import com.vitalgateway.component.message.listener.AlpacaPushSSE;
import com.vitalgateway.config.properties.AlpacaConfiguration;
import com.vitalgateway.object.dto.alpaca.*;
import com.vitalgateway.type.enumerate.RequestType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.Base64;
import java.util.List;

@Log
@Slf4j
@RequiredArgsConstructor
@Service
@org.springframework.core.annotation.Order(1)
public class AlpacaService implements CommandLineRunner {

    private final AlpacaConfiguration.AlpacaConfigProperties alpacaConfigProperties;

    private String AUTHORIZE_TOKEN;

    @Override
    public void run(String... args) throws Exception {
        AUTHORIZE_TOKEN = "Basic " + Base64.getEncoder().encodeToString((alpacaConfigProperties.getAlpacaApiKey() + ":" + alpacaConfigProperties.getAlpacaApiSecret()).getBytes());
    }

    /* **********************************账户模块********************************* */

    /**
     * 查询历史事件，需传入范围，当达到until则将结束
     * 若指定了 until，则必须指定 since
     * 若指定了 until_id，则必须指定 since_id
     * 若指定了 until_ulid，则必须指定 since_ulid
     * since、since_id 和 since_ulid 不能同时使用
     *
     * @return
     */
    public void subscribeToAccountStatus(LocalDate since, LocalDate until, Long sinceId, Long untilId,
                                         String sinceUlid, String untilUlid, AlpacaPushSSE sse) {
        String url = alpacaConfigProperties.getDomain() + "/v1/events/accounts/status";
        Forest.get(url)
                .addQuery("since", since)
                .addQuery("until", until)
                .addQuery("since_id", sinceId)
                .addQuery("until_id", untilId)
                .addQuery("since_ulid", sinceUlid)
                .addQuery("until_ulid", untilUlid)
                .contentType(ContentType.EVENT_STREAM.getValue())
                .addHeader("Authorization", AUTHORIZE_TOKEN)
                .sse()
                .setOnOpen(sse::onOpen)
                .setOnClose(sse::onClose)
                .addOnData(sse::onSSEData)
                .listen();
    }

    /**
     * 创建account
     *
     * @param accountCreationRequest 账户
     * @return
     */
    public com.vitalgateway.object.dto.alpaca.Account createAlpacaAccount(AccountCreationRequest accountCreationRequest) {
        String url = "/v1/accounts";
        return commonRequest(RequestType.POST, url)
                .addBody(accountCreationRequest)
                .execute(com.vitalgateway.object.dto.alpaca.Account.class);
    }

    /**
     * 更新account
     *
     * @param accountId            账户id
     * @param accountUpdateRequest 账户
     * @return
     */
    public AccountExtended updateAlpacaAccount(String accountId, AccountUpdateRequest accountUpdateRequest) {
        String url = StrUtil.format("/v1/accounts/{}", accountId);
        return commonRequest(RequestType.PATCH, url)
                .addBody(accountUpdateRequest)
                .execute(com.vitalgateway.object.dto.alpaca.AccountExtended.class);
    }

    /**
     * 上传账户文件
     *
     * @param accountId             账户
     * @param documentUploadRequest 文件
     */
    public void uploadAlpacaAccountDocument(String accountId, List<DocumentUploadRequest> documentUploadRequest) {
        String url = StrUtil.format("/v1/accounts/{}/documents/upload", accountId);
        commonRequest(RequestType.POST, url)
                .addBody(documentUploadRequest)
                .execute();
    }

    /**
     * 通过id获取账户
     *
     * @param accountId 账户id
     * @return
     */
    public AccountExtended getAlpacaAccount(String accountId) {
        String url = StrUtil.format("/v1/accounts/{}", accountId);
        return commonRequest(RequestType.GET, url)
                .execute(AccountExtended.class);
    }

    /**
     * 检索账户交易详情
     *
     * @param accountId 账户id
     * @return
     */
    public TradeAccount getAlpacaAccountTradeDetail(String accountId) {
        String url = StrUtil.format("/v1/trading/accounts/{}/account", accountId);
        return commonRequest(RequestType.GET, url)
                .execute(TradeAccount.class);
    }

    /* **********************************kyc模块********************************* */

    /**
     * 上传kyc的cip文件
     * @param accountId
     * @param cipInfo
     */
    public void uploadCip(String accountId, CIPInfo cipInfo) {
        String url = StrUtil.format("/v1/accounts/{}/cip", accountId);
        commonRequest(RequestType.POST, url)
                .addBody(cipInfo)
                .execute();
    }


    /**
     * @param requestType 请求类型
     * @param path        path
     * @return forestRequest
     */
    private ForestRequest<?> commonRequest(RequestType requestType, String path) {
        ForestRequest<?> forestRequest = requestType.getForestRequest(alpacaConfigProperties.getDomain() + path);
        forestRequest.contentTypeJson()
                .addInterceptor(CommonForestInterceptor.class)
                .connectTimeout(15000)
                .readTimeout(15000)
                .maxRetryCount(3)
                .maxRetryInterval(100L)
                .addHeader("Authorization", AUTHORIZE_TOKEN);
        return forestRequest;
    }
}
